home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Super Models
/
Hot Super Models.iso
/
unix
/
x11
/
xv200.tar
/
xv-2.00
/
xvscrl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-02
|
10KB
|
370 lines
/*
* xvscrl.c - Scroll Bar handling functions
*
* callable functions:
*
* SCCreate() - creates the Scroll Bar window.
* SCSetRange() - sets min/max/current values of control
* SCSetVal() - sets value of control
* SCRedraw() - redraws scroll bar
* SCTrack() - called when clicked. Operates control 'til mouseup
*/
/*
* Copyright 1989, 1990, 1991, 1992 by John Bradley and
* The University of Pennsylvania
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* The software may be modified for your own purposes, but modified versions
* may not be distributed.
*
* This software is provided "as is" without any expressed or implied warranty.
*
* The author may be contacted via:
* US Mail: John Bradley
* GRASP Lab, Room 301C
* 3401 Walnut St.
* Philadelphia, PA 19104
*
* Phone: (215) 898-8813
* EMail: bradley@cis.upenn.edu
*/
#include "xv.h"
#include "bitmaps.h"
static Pixmap upPix, downPix; /* up/down arrows */
static Pixmap up1Pix, down1Pix; /* up/down arrows (lit up) */
static Pixmap sgray; /* gray stipple for lit scrollbar */
static int pixmaps_built=0; /* true if pixmaps created already */
/* scroll regions */
#define UPLINE 0
#define UPPAGE 1
#define DNLINE 2
#define DNPAGE 3
#define THUMB 4
#define SCRLWAIT 150 /* milliseconds to wait between scrolls */
/* local functions */
#ifdef __STDC__
static int whereInScrl(SCRL *, int, int);
static void drawArrow(SCRL *, int);
#else
static int whereInScrl();
static void drawArrow();
#endif
/***************************************************/
void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page,
fg, bg, func)
SCRL *sp;
Window parent;
int x,y,vert,len,minv,maxv,curv,page;
unsigned long fg,bg;
void (*func)();
{
if (!pixmaps_built) {
upPix = XCreatePixmapFromBitmapData(theDisp, parent,
up_bits, up_width, up_height, fg, bg, dispDEEP);
downPix = XCreatePixmapFromBitmapData(theDisp, parent,
down_bits, down_width, down_height, fg, bg, dispDEEP);
up1Pix = XCreatePixmapFromBitmapData(theDisp, parent,
up1_bits, up1_width, up1_height, fg, bg, dispDEEP);
down1Pix = XCreatePixmapFromBitmapData(theDisp, parent,
down1_bits, down1_width, down1_height,fg,bg,dispDEEP);
sgray = XCreatePixmapFromBitmapData(theDisp, parent,
scrlgray_bits, scrlgray_width, scrlgray_height,fg,bg,dispDEEP);
}
sp->vert = vert;
sp->len = len;
sp->fg = fg;
sp->bg = bg;
sp->uplit = sp->dnlit = 0;
if (vert)
sp->win = XCreateSimpleWindow(theDisp, parent,x,y,up_width-2,len,1,fg,bg);
else FatalError("don't know HOW to make horizontal scrollbar");
if (!sp->win) FatalError("can't create scrollbar window");
sp->tsize = up_width-2; /* really only if vertical */
sp->tmin = up_height-1;
sp->tmax = len - (up_height-1) - sp->tsize;
sp->drawobj = func;
SCSetRange(sp, minv, maxv, curv, page);
XSelectInput(theDisp, sp->win, ExposureMask | ButtonPressMask);
}
/***************************************************/
void SCSetRange(sp, minv, maxv, curv, page)
SCRL *sp;
int minv, maxv, curv, page;
{
if (maxv<minv) maxv=minv;
sp->min = minv; sp->max = maxv; sp->page = page;
sp->active = (minv < maxv);
/* adjust scroll bar background */
if (sp->active) XSetWindowBackgroundPixmap(theDisp, sp->win, sgray);
else XSetWindowBackground(theDisp, sp->win, sp->bg);
sp->val = -99999; /* force a redraw */
SCSetVal(sp, curv);
}
/***************************************************/
int SCSetVal(sp, curv)
SCRL *sp;
int curv;
{
/* returns '0' if no redraw was done */
RANGE(curv, sp->min, sp->max); /* make sure curv is in-range */
if (sp->val == curv) return 0;
sp->val = curv;
if (sp->active)
sp->tpos = sp->tmin + ((sp->tmax - sp->tmin)*(curv - sp->min))
/ (sp->max - sp->min);
SCRedraw(sp);
(sp->drawobj)(); /* redraw whatever the scrollbar controls */
XFlush(theDisp);
return 1;
}
/***************************************************/
void SCRedraw(sp)
SCRL *sp;
{
XSetForeground(theDisp, theGC, sp->fg);
XSetBackground(theDisp, theGC, sp->bg);
XClearWindow(theDisp, sp->win);
if (sp->vert) { /* draw up/down arrows */
drawArrow(sp,UPLINE);
drawArrow(sp,DNLINE);
if (sp->active) { /* a thumb is necessary */
XSetForeground(theDisp, theGC, sp->bg);
XFillRectangle(theDisp, sp->win, theGC,
1, sp->tpos+1, sp->tsize-2, sp->tsize-2);
XSetForeground(theDisp, theGC, sp->fg);
XDrawRectangle(theDisp, sp->win, theGC,
0, sp->tpos, sp->tsize-1, sp->tsize-1);
}
}
}
/***************************************************/
static int whereInScrl(sp,x,y)
SCRL *sp;
int x,y;
{
int v;
/* returns region # that x,y is in. Returns '-1' if none */
v=0;
if (sp->vert) {
if (x<0 || x>up_width-2 || y<0 || y>sp->len) return -1;
v = y;
}
/* once we know it's in scroll bar, only have to check 'v' versus len */
if (v < sp->tmin) return UPLINE;
if (sp->active) {
if (v < sp->tpos) return UPPAGE;
if (v < sp->tpos + sp->tsize) return THUMB;
if (v <= sp->tmax + sp->tsize) return DNPAGE;
}
if (v > sp->tmax+sp->tsize) return DNLINE;
return -1;
}
/***************************************************/
static void drawArrow(sp,arr)
SCRL *sp;
int arr;
{
/* only if vertical */
if (arr == UPLINE) {
if (sp->uplit)
XCopyArea(theDisp, up1Pix, sp->win,theGC,0,0,up_width,up_height,-1,-1);
else
XCopyArea(theDisp, upPix, sp->win,theGC,0,0,up_width,up_height,-1,-1);
}
else if (arr == DNLINE) {
if (sp->dnlit)
XCopyArea(theDisp, down1Pix,sp->win,theGC,0,0,up_width,up_height,
-1, sp->len-(up_height-1));
else
XCopyArea(theDisp, downPix, sp->win,theGC,0,0,up_width,up_height,
-1, sp->len-(up_height-1));
}
XFlush(theDisp);
}
/***************************************************/
void SCTrack(sp,mx,my)
SCRL *sp;
int mx,my;
{
Window rW,cW;
int rx,ry, x,y, ipos, pos, lit, ty, tyoff, ty1;
unsigned int mask;
/* determine in which of the five regions of the scroll bar the mouse
was clicked (upline, downline, uppage, downpage, thumb) */
ty = tyoff = 0;
XSetForeground(theDisp, theGC, sp->fg);
XSetBackground(theDisp, theGC, sp->bg);
/* light up appropriate bit of scroll bar */
ipos = whereInScrl(sp,mx,my);
lit = 1;
switch (ipos) {
case UPLINE: sp->uplit = 1;
if (sp->val > sp->min) SCSetVal(sp,sp->val-1);
Timer(SCRLWAIT);
break;
case DNLINE: sp->dnlit = 1;
if (sp->val < sp->max) SCSetVal(sp,sp->val+1);
Timer(SCRLWAIT);
break;
case UPPAGE: SCSetVal(sp,sp->val - sp->page); break;
case DNPAGE: SCSetVal(sp,sp->val + sp->page); break;
case THUMB: tyoff = sp->tpos - my;
ty = sp->tpos;
XSetState(theDisp, theGC, sp->fg, sp->bg, GXinvert,
sp->fg ^ sp->bg);
XDrawRectangle(theDisp,sp->win,theGC,
0, sp->tpos, sp->tsize-1, sp->tsize-1);
break;
}
/* VERTICAL CODE ONLY */
while (XQueryPointer(theDisp,sp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
if (!(mask & Button1Mask)) break; /* button released */
switch (ipos) {
case THUMB:
/* do thumb tracking */
if (x<-16 || x>16+sp->tsize) { /* outside tracking range */
if (lit) {
lit = 0;
XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
}
}
else { /* inside tracking range */
if (!lit) { /* not lit, just turn on */
lit = 1;
ty = y + tyoff;
RANGE(ty, sp->tmin, sp->tmax);
XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
}
else { /* already lit, more the thumb */
ty1 = y+tyoff;
RANGE(ty1, sp->tmin, sp->tmax);
if (ty != ty1) { /* but only if mouse has moved */
XDrawRectangle(theDisp, sp->win, theGC,
0,ty,sp->tsize-1,sp->tsize-1);
ty = ty1;
XDrawRectangle(theDisp, sp->win, theGC,
0,ty,sp->tsize-1,sp->tsize-1);
}
}
}
break;
case UPLINE:
case DNLINE: /* arrows */
pos = whereInScrl(sp,x,y);
if (pos == ipos) {
if (!lit) {
lit = 1;
if (ipos == UPLINE) { sp->uplit = 1; drawArrow(sp,UPLINE); }
else { sp->dnlit = 1; drawArrow(sp,DNLINE); }
}
else {
if (sp->val > sp->min && pos==UPLINE) {
SCSetVal(sp, sp->val-1);
Timer(SCRLWAIT);
}
else if (sp->val < sp->max && pos==DNLINE) {
SCSetVal(sp, sp->val+1);
Timer(SCRLWAIT);
}
}
}
else {
if (lit) {
lit = 0;
if (ipos == UPLINE) { sp->uplit = 0; drawArrow(sp,UPLINE); }
else { sp->dnlit = 0; drawArrow(sp,DNLINE); }
}
}
break;
}
}
if (ipos == THUMB) {
if (lit) /* turn off */
XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
XSetState(theDisp, theGC, sp->fg, sp->bg, GXcopy, AllPlanes);
if (lit && ty != sp->tpos) { /* if thumb was moved, ROUND to new val */
int dt, dv;
dt = sp->tmax - sp->tmin;
dv = sp->max - sp->min;
SCSetVal(sp, sp->min + (dv*(ty - sp->tmin)+dt/2) / dt);
}
}
if (lit && ipos == UPLINE) { sp->uplit = 0; drawArrow(sp, UPLINE); }
if (lit && ipos == DNLINE) { sp->dnlit = 0; drawArrow(sp, DNLINE); }
}